`timescale 1ns/100ps

`include "sim_glb.sv"

module tc;

localparam          CNT_BW                  = 2;    // the max number of uncompleted pulse is 2^CNT_BW
localparam          SYNC_NUM_D2S            = 3;    // min gap between two transmission about SYNC_NUM_D2S+SYNC_NUM_S2D+2 clock steps
localparam          SYNC_NUM_S2D            = 3;
localparam          PLS_NUM                 = 1000;

reg                                         rst_src_n;
reg                                         clk_src;

reg                                         src_pls;    // keep src_pls 1'b1 when src_rdy 1'b0 unless missing pulse make no difference to system
wire                                        src_rdy;    // ignore src_rdy and set MISS_PLS_CHKEN=0 if not care missing pulse

reg                                         rst_dst_n;
reg                                         clk_dst;

wire                                        dst_pls;
reg                                         dst_rdy;

initial begin:CRG
    rst_src_n=1'b0;
    clk_src=1'b0;
    rst_dst_n=1'b0;
    clk_dst=1'b0;

    fork
        rst_src_n=#100.5 1'b1;
        rst_dst_n=#100.5 1'b1;

        forever clk_src=#4 ~clk_src;
        forever clk_dst=#5 ~clk_dst;
    join
end

RGRS_MNG    rgrs;
initial begin:REGRESS
    rgrs = new("tc_sync_pls", 2);

    rgrs.wait_chks_done(100_000_000);
end

initial begin:GEN_SRC
    integer             gap;

    src_pls = 1'b0;
    @(posedge rst_src_n);
    @(posedge clk_src);

    repeat (PLS_NUM) begin
        gap = $urandom_range(0, 10);
        repeat(gap) begin
            @(posedge clk_src);
        end
        src_pls  = `U_DLY 1'b1;
        @(posedge clk_src);

        while(src_rdy==1'b0) begin
            @(posedge clk_src);
        end
        src_pls  = `U_DLY 1'b0;
    end

    rgrs.one_chk_done("req is done.");
end

sync_pls #(
        .CNT_BW                         (CNT_BW                         ),	// the max number of uncompleted pulse is 2^CNT_BW
        .SYNC_NUM_D2S                   (SYNC_NUM_D2S                   ),	// min gap between two transmission about SYNC_NUM_D2S+SYNC_NUM_S2D+2 clock steps
        .SYNC_NUM_S2D                   (SYNC_NUM_S2D                   )
) u_sync_pls ( 
        .rst_src_n                      (rst_src_n                      ),
        .clk_src                        (clk_src                        ),

        .src_pls                        (src_pls                        ),	// keep src_pls 1'b1 when src_rdy 1'b0 unless missing pulse make no difference to system
        .src_rdy                        (src_rdy                        ),	// ignore src_rdy and set MISS_PLS_CHKEN

        .rst_dst_n                      (rst_dst_n                      ),
        .clk_dst                        (clk_dst                        ),

        .dst_pls                        (dst_pls                        ),
        .dst_rdy                        (dst_rdy                        )
);

initial begin:CHK_DST
    @(posedge rst_dst_n);

    repeat(PLS_NUM) begin
        @(posedge clk_dst);
        while((dst_pls==1'b0) || (dst_rdy==1'b0)) begin
            @(posedge clk_dst);
        end
    end
    rgrs.one_chk_done("chk is done.");
end

always@(posedge clk_dst or negedge rst_dst_n) begin
    if (rst_dst_n==1'b0) begin
        dst_rdy <=`U_DLY 1'b0;
    end else begin
        dst_rdy <=`U_DLY ($urandom_range(1, 100)<=20) ? 1'b1 : 1'b0;
    end
end

endmodule

